package com.mentalhealthplatform.global.log;

import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.aspectj.lang.ProceedingJoinPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;

import jakarta.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;

@Aspect
@Component
public class GeneralLogAspect {

    private static final Logger logger = LoggerFactory.getLogger(GeneralLogAspect.class);

    @Autowired
    private HttpServletRequest request;

    // 定义切入点，匹配带有@LogAction注解的方法
    @Pointcut("@annotation(com.mentalhealthplatform.global.log.LogAction)")
    public void logActionPointcut() { }

    // 环绕通知：在方法执行前后记录日志，包括操作时间、操作人、操作IP
    @Around("logActionPointcut()")
    public Object logOperation(ProceedingJoinPoint joinPoint) throws Throwable {
        // 记录操作时间
        LocalDateTime operationTime = LocalDateTime.now();

        // 获取操作名称和描述
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        LogAction logAction = signature.getMethod().getAnnotation(LogAction.class);
        String operationName = logAction.value().isEmpty() ? signature.getName() : logAction.value();
        String description = logAction.description();

        // 获取操作IP
        String ipAddress = request.getRemoteAddr();

        // 判断是否为登录操作
        boolean isLoginOperation = "login".equalsIgnoreCase(operationName);

        // 记录操作开始日志
        if (isLoginOperation) {
            logger.info("开始执行登录操作 - IP地址: {}, 时间: {}, 操作: {}, 描述: {}",
                    ipAddress, operationTime, operationName, description);
        } else {
            // 非登录操作，获取当前用户
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            String operator = (authentication != null) ? authentication.getName() : "Anonymous";
            logger.info("开始执行操作 - 操作人: {}, IP地址: {}, 时间: {}, 操作: {}, 描述: {}",
                    operator, ipAddress, operationTime, operationName, description);
        }

        long start = System.currentTimeMillis();
        Object result;

        try {
            // 执行方法
            result = joinPoint.proceed();
        } catch (Throwable throwable) {
            if (isLoginOperation) {
                logger.error("登录操作失败 - 操作: {}, 异常: {}", operationName, throwable.getMessage());
            } else {
                Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
                String operator = (authentication != null) ? authentication.getName() : "Anonymous";
                logger.error("操作失败 - 操作人: {}, 操作: {}, 异常: {}", operator, operationName, throwable.getMessage());
            }
            throw throwable;
        }

        long executionTime = System.currentTimeMillis() - start;

        // 记录操作成功日志
        if (isLoginOperation) {
            // 登录成功后获取操作人
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            String operator = (authentication != null) ? authentication.getName() : "Unknown";
            logger.info("登录成功 - 操作人: {}, 执行时间: {} ms",
                    operator, executionTime);
        } else {
            // 非登录操作
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            String operator = (authentication != null) ? authentication.getName() : "Anonymous";
            logger.info("操作完成 - 操作人: {}, 操作: {}, 执行时间: {} ms, 返回结果: {}",
                    operator, operationName, executionTime, result);
        }

        return result;
    }
}
